
package models.spider.index;

import static models.Store.save;

import java.util.Calendar;
import java.util.Collection;
import java.util.Date;

import models.spider.policy.IPolicy;
import models.spider.policy.Policy;

/**
 * 
 * @author laurent@opprecht.info
 */
public class Queue {

    static Queue create(final IPolicy policy, final Index index) {
        return new Queue(policy, index);
    }

    protected IPolicy policy;
    protected Index   index;

    public Queue(final IPolicy policy, final Index index) {
        this.policy = policy;
        this.index = index;
    }

    public Queue(final IPolicy policy) {
        this(policy, new Index());
    }

    public Queue() {
        this(Policy.YES);
    }

    public IPolicy getPolicy() {
        return policy;
    }

    public boolean has(final String url) {
        Entry entry = index.get(url);
        if (entry == null) {
            return false;
        }
        Date l = limit();
        boolean result = entry.modified.before(l);
        return result;
    }

    public boolean add(final String url) {
        if (!policy.accept(url)) {
            return false;
        }

        if (has(url)) {
            return true;
        }
        if (index.has(url)) {
            return true;
        }
        Entry entry = Entry.get(url);

        save(entry);
        return true;
    }

    public boolean refresh(final String url) {
        if (!policy.accept(url)) {
            return false;
        }

        if (has(url)) {
            return true;
        }

        Entry entry = index.get(url);
        if (entry != null) {
            entry.setModified(Entry.startOfTime());
            save(entry);
            return true;
        }

        entry = Entry.get(url);
        save(entry);
        return true;
    }

    public void addAll(final Collection<String> urls) {
        for (String url : urls) {
            add(url);
        }
    }

    public Entry peek() {
        Date l = limit();
        Entry result = index.bottom(l);
        return result;
    }

    public Entry remove() {
        Entry result = peek();
        if (result == null) {
            return result;
        }
        result.setModified(new Date());

        save(result);
        return result;
    }

    protected Date limit() {
        Calendar calendar = Calendar.getInstance();
        calendar.add(Calendar.DATE, -1);
        Date result = calendar.getTime();
        return result;
    }
}
